package edu.dayu.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import edu.dayu.enums.OrderStatusEnum;
import edu.dayu.enums.PaymentStatusEnum;
import edu.dayu.enums.PaymentTypeEnum;
import edu.dayu.enums.RefundStatusEnum;
import edu.dayu.exception.YyghException;
import edu.dayu.helper.HttpRequestHelper;
import edu.dayu.model.order.OrderInfo;
import edu.dayu.model.order.PaymentInfo;
import edu.dayu.model.order.RefundInfo;
import edu.dayu.result.ResultCodeEnum;
import edu.dayu.service.*;
import edu.dayu.util.ConstantPropertiesUtils;
import edu.dayu.vo.order.SignInfoVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class AliPayServiceImpl implements AliPayService {
    @Autowired
    private OrderService orderService;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @DubboReference
    private HospitalSetDubbo hospitalSetDubbo;

    @Autowired
    private RefundInfoService refundInfoService;

    @Override
    public Map<String,String> goAliPay(Long orderId) {
//        Map<String,String> payMap = (Map<String, String>) redisTemplate.opsForValue().get(orderId.toString());
//        if(null != payMap) return payMap;
        //根据id获取订单信息
        OrderInfo order = orderService.getById(orderId);
        // 保存交易记录
        paymentService.savePaymentInfo(order, PaymentTypeEnum.ALIPAY.getStatus());
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(ConstantPropertiesUtils.GATEWAYURL,
                ConstantPropertiesUtils.APPID,
                ConstantPropertiesUtils.MERCHANTPRIVATEKEY,
                "json",
                ConstantPropertiesUtils.CHARSET,
                ConstantPropertiesUtils.ALIPAYPUBLICKEY,
                ConstantPropertiesUtils.SIGNTYPE);
        //设置请求参数
        AlipayTradePrecreateRequest alipayRequest = new AlipayTradePrecreateRequest();
        alipayRequest.setReturnUrl(ConstantPropertiesUtils.RETURNURL);
        alipayRequest.setNotifyUrl(ConstantPropertiesUtils.NOTIFYURL);

        // 商户订单号, 商户网站订单系统中唯一订单号, 必填
        String out_trade_no = order.getOutTradeNo();
        // 付款金额, 必填 单位元
        String total_amount = order.getAmount().toString();  // 测试用 1分钱
        // 订单名称, 必填
//        String subject = "大鱼-付款用户[" + order.getPatientName() + "]";
        String subject = "大鱼";
        // 商品描述, 可空, 目前先用订单名称
        String body = subject;
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no",out_trade_no);
        bizContent.put("total_amount",total_amount);
        bizContent.put("subject",subject);
        alipayRequest.setBizContent(bizContent.toString());

        // 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）。 该参数数值不接受小数点， 如 1.5h，可转换为 90m。
//        String timeout_express = "1h";
//        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
//                + "\"total_amount\":\""+ total_amount +"\","
//                + "\"subject\":\""+ subject +"\","
//                + "\"body\":\""+ body +"\","
//                + "\"timeout_express\":\""+ timeout_express +"\","
//                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        //请求
        String alipayForm = "";
        Map<String,String> map = new HashMap<>();
        try {
            AlipayTradePrecreateResponse response = alipayClient.execute(alipayRequest);
            System.out.println(response);
            alipayForm = response.getQrCode();
            redisTemplate.opsForValue().set(orderId.toString(),alipayForm,1000, TimeUnit.MINUTES);
            map.put("codeUrl",alipayForm);
            map.put("orderId",orderId.toString());
            map.put("amount",order.getAmount().toString());
            return map;
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public AlipayTradeQueryResponse queryPayStatus(Long orderId, String paymentType) {
        try {
            OrderInfo orderInfo = orderService.getById(orderId);
            //1、封装参数
            //获得初始化的AlipayClient
            AlipayClient alipayClient = new DefaultAlipayClient(ConstantPropertiesUtils.GATEWAYURL,
                    ConstantPropertiesUtils.APPID,
                    ConstantPropertiesUtils.MERCHANTPRIVATEKEY,
                    "json",
                    ConstantPropertiesUtils.CHARSET,
                    ConstantPropertiesUtils.ALIPAYPUBLICKEY,
                    ConstantPropertiesUtils.SIGNTYPE);
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", orderInfo.getOutTradeNo());
            //bizContent.put("trade_no", "2014112611001004680073956707");
            request.setBizContent(bizContent.toString());
            //返回响应结果
            AlipayTradeQueryResponse response = alipayClient.execute(request);

            return response;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public void paySuccess(String outTradeNo, Integer paymentType, AlipayTradeQueryResponse response) {
        PaymentInfo paymentInfo = this.getPaymentInfo(outTradeNo, paymentType);
        if (null == paymentInfo) {
            throw new YyghException(ResultCodeEnum.PARAM_ERROR);
        }
        if (paymentInfo.getPaymentStatus() != PaymentStatusEnum.UNPAID.getStatus()) {
            return;
        }
        //修改支付状态
        PaymentInfo paymentInfoUpd = new PaymentInfo();
        paymentInfoUpd.setPaymentStatus(PaymentStatusEnum.PAID.getStatus());
        paymentInfoUpd.setTradeNo(response.getTradeNo());
        paymentInfoUpd.setCallbackTime(new Date());
        paymentInfoUpd.setCallbackContent(response.toString());
        this.updatePaymentInfo(outTradeNo, paymentInfoUpd);
        //修改订单状态
        OrderInfo orderInfo = orderService.getById(paymentInfo.getOrderId());
        orderInfo.setOrderStatus(OrderStatusEnum.PAID.getStatus());
        orderService.updateById(orderInfo);
        // 调用医院接口，通知更新支付状态
        SignInfoVo signInfoVo
                = hospitalSetDubbo.getSignInfoVo(orderInfo.getHoscode());
        if(null == signInfoVo) {
            throw new YyghException(ResultCodeEnum.PARAM_ERROR);
        }
//        Map<String, Object> reqMap = new HashMap<>();
//        reqMap.put("hoscode",orderInfo.getHoscode());
//        reqMap.put("hosRecordId",orderInfo.getHosRecordId());
//        reqMap.put("timestamp", HttpRequestHelper.getTimestamp());
//        String sign = HttpRequestHelper.getSign(reqMap, signInfoVo.getSignKey());
//        reqMap.put("sign", sign);
//        JSONObject result = HttpRequestHelper.sendRequest(reqMap, signInfoVo.getApiUrl()+"/order/updatePayStatus");
//        if(result.getInteger("code") != 200) {
//            throw new YyghException(result.getString("message"), ResultCodeEnum.FAIL.getCode());
//        }
    }

    @Override
    public Boolean refund(Long orderId) {
        try {
            PaymentInfo paymentInfoQuery = paymentService.getPaymentInfo(orderId, PaymentTypeEnum.ALIPAY.getStatus());
            RefundInfo refundInfo = refundInfoService.saveRefundInfo(paymentInfoQuery);
            if(refundInfo.getRefundStatus().intValue() == RefundStatusEnum.REFUND.getStatus().intValue()) {
                return true;
            }
            AlipayClient alipayClient = new DefaultAlipayClient(ConstantPropertiesUtils.GATEWAYURL,
                    ConstantPropertiesUtils.APPID,
                    ConstantPropertiesUtils.MERCHANTPRIVATEKEY,
                    "json",
                    ConstantPropertiesUtils.CHARSET,
                    ConstantPropertiesUtils.ALIPAYPUBLICKEY,
                    ConstantPropertiesUtils.SIGNTYPE);
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no",paymentInfoQuery.getOutTradeNo());
            bizContent.put("trade_no", paymentInfoQuery.getTradeNo());
            bizContent.put("refund_amount",refundInfo.getTotalAmount() );
//            bizContent.put("out_request_no", "HZ01RF001");

            //// 返回参数选项，按需传入
            //JSONArray queryOptions = new JSONArray();
            //queryOptions.add("refund_detail_item_list");
            //bizContent.put("query_options", queryOptions);

            request.setBizContent(bizContent.toString());
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            if(response.isSuccess()){
                refundInfo.setCallbackTime(new Date());
                refundInfo.setTradeNo(response.getTradeNo());
                refundInfo.setRefundStatus(RefundStatusEnum.REFUND.getStatus());
                refundInfo.setCallbackContent(JSONObject.toJSONString(response));
                refundInfoService.updateById(refundInfo);
                return true;
            } else {
                return false;
            }
        }  catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }



        /**
     * 获取支付记录
     */
    private PaymentInfo getPaymentInfo(String outTradeNo, Integer paymentType) {
        QueryWrapper<PaymentInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("out_trade_no", outTradeNo);
        queryWrapper.eq("payment_type", paymentType);
        return paymentService.getOne(queryWrapper);
    }
    /**
     * 更改支付记录
     */
    private void updatePaymentInfo(String outTradeNo, PaymentInfo paymentInfoUpd) {
        QueryWrapper<PaymentInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("out_trade_no", outTradeNo);
        paymentService.update(paymentInfoUpd, queryWrapper);
    }
}
